package com.jrx.anytxn.param.service.investor.impl;

import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.dto.investor.FileBean;
import com.jrx.anytxn.param.entity.GaInvestorSubjectConfig;
import com.jrx.anytxn.param.entity.GaSubjectDetailInfo;
import com.jrx.anytxn.param.entity.PrInvestorTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.mapper.ext.ExtGaSubjectDetailInfoMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrInvestorTableMapper;
import com.jrx.anytxn.param.service.investor.IInvestorParamFileService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @program: anytxn-cf-transaction
 * @description:
 * @author: xiaoyu.jing
 * @date: 2020-06-09 09:51
 **/
@Service
public class InvestorParamFileServiceImpl implements IInvestorParamFileService {

    private final Logger logger = LoggerFactory.getLogger(InvestorParamFileServiceImpl.class);

    @Autowired
    private IOrganizationTableService organizationTableService;
    @Resource
    private ExtGaSubjectDetailInfoMapper extGaSubjectDetailInfoMapper;
    @Resource
    private ExtPrInvestorTableMapper extPrInvestorTableMapper;


    @Override
    public FileBean createGlFileMessage(GaInvestorSubjectConfig item) {
        FileBean fileBean = new FileBean();
        StringBuilder sb = new StringBuilder();
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(Constant.DEFAULT_ORG_NUMBER);
        Date today = org.getToday();
        GaSubjectDetailInfo info = extGaSubjectDetailInfoMapper.selectByUnique(item.getSubjectId(),item.getTenantId(),today);
        if(null == info){
            return null;
        }
        sb.append(info.getSubjectId() == null ? "" : info.getSubjectId()).append(Constant.separator);
        String detailDate = today == null ? "" : DateUtils.formatDate(today, DateUtils.DATE_PATTERN_ANOTHER);
        sb.append(detailDate).append(Constant.separator);

        sb.append(info.getDebitCount() == null ? "0" : info.getDebitCount()).append(Constant.separator);
        sb.append(info.getDebitAmount() == null ? "0.00" : info.getDebitAmount().toPlainString()).append(Constant.separator);
        sb.append(info.getCreditCount() == null ? "0" : info.getCreditCount()).append(Constant.separator);
        sb.append(info.getCreditAmount() == null ? "0.00" : info.getCreditAmount().toPlainString()).append(Constant.separator);
        sb.append(info.getDebitBal() == null ? "0.00" : info.getDebitBal().toPlainString()).append(Constant.separator);
        sb.append(info.getCreditBal() == null ? "0.00" : info.getCreditBal().toPlainString()).append(Constant.separator);
        sb.append( "\r\n");
        fileBean.setInvestorId(item.getInvestorId());
        fileBean.setFileString(sb.toString());
        return fileBean;
    }


    @Override
    public void generatingFile(List<String> messageList, String reportingPath, String investorId, String fileName, String fileType) throws IOException {

        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(Constant.DEFAULT_ORG_NUMBER);
        String toDay = DateUtils.format(org.getToday(), "yyyyMMdd");

        String collectionFileName = fileType + "_" + toDay + "_" + fileName + ".txt";

        String filePath = reportingPath + File.separator + org.getTenantId() + File.separator + investorId + File.separator + toDay + File.separator;

        Path reportingFile = Paths.get(filePath + collectionFileName);

        int i = 0;

        try (
                FileWriter bfw = new FileWriter(reportingFile.toFile(), true);
                BufferedWriter writer = new BufferedWriter(bfw, 10240);
        ) {
            if (reportingFile.toFile().length() != 0) {
                writer.write("\r\n");
            }
            for (String message : messageList) {
                writer.write(message);
            }
            writer.flush();
        }
    }

    @Override
    public void mergeFile(PrOrganizationTable org, String filePath, String fileName) throws IOException {
        logger.info("开始合并分库文件");

        Date bussinessDate = org.getToday();
        String toDay = DateUtils.format(bussinessDate, "yyyyMMdd");
        List<PrInvestorTable> investorList = extPrInvestorTableMapper.selectAllByTableStatus(Constant.STATUS_1);
        if (CollectionUtils.isEmpty(investorList)) {
            return;
        }
        for (PrInvestorTable investorTable : investorList) {
            String investorId = investorTable.getInvestorId();
            String investorPath = filePath + File.separator + org.getTenantId() + File.separator + investorId + File.separator + toDay + File.separator;

            //生成日初借据文件
            mergeInvestorFile(investorPath, toDay, Constant.DAY_ORDER_FILE_NAME);

            //生成日初分期文件
            mergeInvestorFile(investorPath, toDay, Constant.DAY_PLAN_FILE_NAME);

            //生成借款借据文件
            mergeInvestorFile(investorPath, toDay, Constant.LOAN_ORDER_FILE_NAME);

            //生成借款分期文件
            mergeInvestorFile(investorPath, toDay, Constant.LOAN_PLAN_FILE_NAME);

            //生成还款借据文件
            mergeInvestorFile(investorPath, toDay, Constant.REPAY_ORDER_FILE_NAME);

            //生成还款分期文件
            mergeInvestorFile(investorPath, toDay, Constant.REPAY_PLAN_FILE_NAME);

            //生成每日利息文件
            mergeInvestorFile(investorPath, toDay, Constant.INTR_FILE_NAME);

            //生成每日借据形态转换文件
            mergeInvestorFile(investorPath, toDay, Constant.TRANS_FILE_NAME);

            //生成每日会计分录流水文件
            mergeInvestorFile(investorPath, toDay, Constant.ACCOUNTING_FILE_NAME);

            //生成每日联合贷日初分期文件
            mergeInvestorFile(investorPath, toDay, Constant.GL_FILE_NAME);

            File okFile = new File(investorPath + toDay + ".ok");
            if (!okFile.exists()) {
                //按照租户生成OK文件
                okFile.createNewFile();
            }
        }
    }

    private void mergeInvestorFile(String investorPath, String toDay, String fileType) throws IOException {
        //获取目录下所有文件
        File file = new File(investorPath);
        File[] tempList = file.listFiles();

        List<File> mergeList = new ArrayList<>();
        if (ArrayUtils.isEmpty(tempList)) {
            throw new IOException("生成文件失败");
        }

        assert tempList != null;
        for (int i = 0; i < tempList.length; i++) {
            String fileName = tempList[i].getName();
            if(fileType.length()>fileName.length()){
                continue;
            }
            String subStr = fileName.substring(0, fileType.length());
            if (fileType.equals(subStr)) {
                mergeList.add(tempList[i]);
            }
        }
        //合并文件
        File resultFile = new File(investorPath + fileType + "_" + toDay + ".txt");
        try (FileChannel resultFileChannel = new FileOutputStream(resultFile, true).getChannel()) {
            for (int i = 0; i < mergeList.size(); i++) {
                try (FileChannel blk1 = new FileInputStream(mergeList.get(i)).getChannel()) {
                    if (i == 0 && blk1.size() == 0) {
                       resultFile.createNewFile();
                    } else if (blk1.size() != 0) {
                        if (i != 0) {
                            //换行
                            ByteBuffer buf = ByteBuffer.allocate(48);
                            buf.clear();
                            buf.put("\r\n".getBytes());
                            buf.flip();
                            while (buf.hasRemaining()) {
                                resultFileChannel.write(buf);
                            }
                        }
                        //写入新文件
                        resultFileChannel.transferFrom(blk1, resultFileChannel.size(), blk1.size());
                    }
                }
            }
        }

        // 获取文件总条数
        long count = Files.lines(Paths.get(investorPath + fileType + "_" + toDay + ".txt")).count();

        // 生成OK文件
        File okFile = new File(investorPath + fileType + "_" + toDay + ".ok");
        try (FileWriter fw = new FileWriter(okFile);
             BufferedWriter writer = new BufferedWriter(fw)) {
            writer.write(count + "");
            writer.flush();
        }
    }
}
